
import axios from 'axios';
import qs from 'qs';
import { putToken, getToken } from './CommonUtils';

const ErrorMessage = {
    timeout: '接口调用超时',
    network: '网络错误',
    other: '系统错误',
    contentType: '返回的http头Content-type中没有application/json',
    contentDisposition: '返回的http头content-disposition中没有附件名称'
};

const CodeMessage = {
    400: '400：发出的请求有错误',
    401: '401：没有权限',
    403: '403：禁止的访问',
    404: '404：找不到接口',
    405: '405：调用方法错误',
    406: '406：请求的格式不可得',
    410: '410：请求的资源被永久删除',
    415: '415：不支持的媒体类型',
    500: '500：服务器发生错误',
    502: '502：网关错误',
    503: '503：服务不可用',
    504: '504：网关超时'
};

const  axiosOptions = {
    baseURL: 'http://permission.zhdst.cn:9080',
    //  允许在向服务器发送前，修改config.data
    // 只能用在 "PUT", "POST" 和 "PATCH" 这几个请求方法
    // 后面数组中的函数必须返回一个字符串，或 ArrayBuffer，或 Stream
    // 这里是一个函数数组,可能是按顺序调用。这里目前只处理application/x-www-form-urlencoded。如果是application/json
    transformRequest: [function (data, headers) {
        // 对 data 进行任意转换处理
        console.log('transformRequest=data==', data);
        console.log('transformRequest=headers==', headers);
        console.log('headers[\'Content-Type\']===', headers['Content-Type']);
        // if ( headers['Content-Type'].toUpperCase() === 'application/json;charset=utf-8'.toUpperCase() ) {
            //let re = qs.stringify(data, {allowDots: true, arrayFormat: 'indices'});
            //https://baijiahao.baidu.com/s?id=1713918207856319740&wfr=spider&for=pc
            //https://www.npmjs.com/package/qs
            //indices: false:重要，后端才能取到数组
            let re = qs.stringify(data, {encode: true, allowDots: true, allowSparse: true, indices: false, arrayLimit: 10000});
            // console.log('transformRequest=data=re=', re);
            return re;
        // }
        // return data;
    }],
    withCredentials: false, // 每次请求不携带cookies信息
    timeout: 15000,
    headers: {version: '1.0.0'},
    //  paramsSerializer只处理通过config.params传过来的数据，
    //  config.params必须是一个无格式对象(plain object)或 URLSearchParams 对象
    //  所谓的无格式的对象就是属性值皆为字符串的对象
    //0.x版本
    // paramsSerializer: function(params) {
    //     return qs.stringify(params, {allowDots: true, arrayFormat: 'indices'});
    // },
    //1.x版本
    paramsSerializer: { 
        serialize:function(params) {
         return qs.stringify(params, {allowDots: true, arrayFormat: 'indices'})
       }
    },
};

function putHeaders(headers, key, value) {
    if (value === undefined || key === undefined) {
        return false
    } else {
        headers[key] = value
    }
}
//下载文件,这里后台传回的是二进制数据,是什么格式(xls,doc,jpeg等)由后台确定,前端使用blob来保存文件.
async function downloadFile(response) {
    let data = response.data;
    console.log('downloadFile================data===', data);
    const config = response.config;
    const headers = response.headers;
    console.log('downloadFile===========headers1=', headers, JSON.stringify(headers));
    //这里将后台输出的错误信息显示出来
    let result = await data.text();
    try {
        //如果能正确解析JSON，则表示返回的是错误信息
        result = JSON.parse(result);
        if ( result.code ) {
            return result;
        }
    }catch( error ) {
        console.log('downloadFile================error===', error);
    }
    //处理文件下载
    if ( response.headers['content-disposition']) {
        let downLoadMark = response.headers['content-disposition'].split(';');
        if ( downLoadMark[0] === 'attachment' ) {
            let fileName = downLoadMark[1].split('filename=')[1];
            fileName = window.decodeURI(fileName);
            const url = window.URL.createObjectURL(new Blob([data]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', fileName);
            document.body.appendChild(link);
            link.click();
            window.URL.revokeObjectURL(link.href);  //释放内存
            link.remove();
            return {code: '0', message: '下载成功.'};
        }        
    }
    return {code: '100', message: '下载失败:返回头中没有content-disposition和attachment'};
}

//定义一个用户没有登录时，转向的登录页面。默认为权限系统中的租户登录。
//用户可以在main.js中修改。(从租户配置中取或通过打包参数)
export let LoginPath = '/permission/tenant/login';

//新建一个带配置的 axios 实例
const axiosService = axios.create(axiosOptions);
//axiosService.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
//重要：修改默认值.因为默认值是:application/x-www-form-urlencoded
axiosService.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
//axiosService.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
// request拦截器
axiosService.interceptors.request.use(
    config => {
        console.log("axiosService.interceptors.request.use ==========");
        let token = getToken();
        if ( token ) {
            console.log( token );
            config.headers['token'] = token;     // 让每个请求携带自定义token 请根据实际情况自行修改
            Object.assign(config.headers, { 'token': token });
        }
        console.log("axiosService.interceptors.request.use =====config=====" + JSON.stringify(config));
        return config;
    },
    error => {
        alert("request error");
        console.log("error === axiosService.interceptors.request.use" + JSON.stringify(error));
        return Promise.reject(error);
});

// respone拦截器
axiosService.interceptors.response.use(
    async response => {   //response.status === 200，会执行这里。其它执行error
        let result = response.data;
        if ( !result.code ) {       //返回的数据中不存在code，可能是下载文件，使用downloadFile方法处理文件下载,同时返回消息数据
            result = await downloadFile(response);
        }
        console.log("success== axiosService.interceptors.response.use ========" + JSON.stringify(response));
        //data:服务返回的用户数据。status:此次访问的状态 http code为200，则表示请求服务器成功。
        console.log("业务处理结果200:" + response.data.code + response.data.message);
        let webAddress = window.location.protocol + '//' + window.location.host;
        if ( result.code === "0") {     //业务处理结果成功.
            console.log("业务处理结果0:" + result.code + result.message);
            return result;
        }else if ( result.code === "-1") {    //未登录,
            console.info('result.code === 1未1登录');
            window.location.href = webAddress;
            console.info('result.code === 1未2登录');
            return Promise.reject(result);
        }else if ( result.code ===  "-2") {   //登录过期了
            window.location.href = webAddress;
            return Promise.reject(result);
        }else if ( result.code ===  "-3" ) {    //没有访问此功能的权限
            return Promise.reject(result);
        }else {
            return Promise.reject(result);      //这里一定要作为异常抛出，axios.get中的catch会捕获此异常。
        }
    },
    error => {
        console.log("error== axiosService.interceptors.response.use ========" + JSON.stringify(error));
        if ( error.name === "Error" ) {}    //如果有错，会抛出error， 所以这里不显示报错信息。
        return Promise.reject(error)
    }
);


export let ServiceCenter = { SERVICE_CENTER_PERMISSION: 'http://permission.zhdst.cn:9080' };
export let AuthorizedMenus = { ready: false, authorized: {} };

export function isLeftRightLayout() {
    if ( ServiceCenter.HOST_LAYOUT === 'TOP_BOTTOM' ) {
        return false;
    }else if ( ServiceCenter.HOST_LAYOUT === 'LEFT_RIGHT' ) {
        return true;
    }else {
        return true;
    }
}
export default {
    /**
     *
     * @param url: 取租户信息的徽服务.
     * @param data: 数据，其中hostName为必须.
     * @param serviceCenterCode :配置中心服务的CODE,如果为空或者没有定义，则默认为SERVICE_CENTER_PERMISSION
     */
    async axiosTenant(url, data, serviceCenterCode) {
        if ( serviceCenterCode === undefined || serviceCenterCode === '' || serviceCenterCode == null ) {
            serviceCenterCode = 'SERVICE_CENTER_PERMISSION';
        }
        //=start==以下使用同步取数。因为axios是异步方式，而租户数据一定要同步取回后，再进行后一步的操作.
        //https://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html 重要文章
        let tenant = {};
        let xhr = new XMLHttpRequest();
        let re = qs.stringify(data, {encode: true, allowDots: true, allowSparse: true, indices: false, arrayLimit: 10000});
        xhr.open('GET', ServiceCenter[serviceCenterCode] + url + '?' + re, false);
        xhr.onreadystatechange = function(e){
            if ( xhr.readyState == 4 && xhr.status == 200 ) {
                let responseJSON = JSON.parse(xhr.responseText);
                tenant = responseJSON.datum;
            } else {

            }
        };
        xhr.send();
        //=end===========================
        console.log('axiosTenant=====', tenant);
        if ( tenant === undefined ) {
            this.warning({
                title: '警告',
                position: 'bottom-right',
                message: '从中台取租户信息出错，请检查域名是否正确或中台服务是否开启.中台服务代码:' + serviceCenterCode,
                type: 'warning'
            });
            return ;
        }else {
            ServiceCenter.tenantId = tenant.snid;
            return tenant.snid;
        }
    },
    /**
     *
     * @param url: 取每个租户服务中心的配置的徽服务.
     * @param data: 租户信息，其中租户ID为必须.
     * @param serviceCenterCode :配置中心服务的CODE,如果为空或者没有定义，则默认为SERVICE_CENTER_PERMISSION
     */
    async axiosServiceCenter(url, data, serviceCenterCode) {
        if ( serviceCenterCode === undefined || serviceCenterCode === '' || serviceCenterCode == null ) serviceCenterCode = 'SERVICE_CENTER_PERMISSION';
        //let serviceCenters = await this.axiosGet(url, data, serviceCenterCode, {showMessage: false});
        //=start==以下使用同步取数。因为axios是异步方式，而配置数据一定要同步取回后，再进行后一步的操作.
        //https://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html 重要文章
        let serviceCenters = [];
        let xhr = new XMLHttpRequest();
        let re = qs.stringify(data, {encode: true, allowDots: true, allowSparse: true, indices: false, arrayLimit: 10000});
        xhr.open('GET', ServiceCenter[serviceCenterCode] + url + '?' + re, false);
        xhr.onreadystatechange = function(e){
            //console.log('xhr=ok===========', xhr);
            if ( xhr.readyState == 4 && xhr.status == 200 ) {
                //console.log('xhr=ok===========', xhr);
                let responseJSON = JSON.parse(xhr.responseText);
                serviceCenters = responseJSON.data;
            } else {
                //console.log('xhr=error===========', xhr);
            }
        };
        xhr.send();
        //=end===========================

        console.log('serviceCenters in axiosServiceCenter===', serviceCenters);
        if ( serviceCenters === undefined ) {
            this.warning({
                title: '警告',
                position: 'bottom-right',
                message: '从中台取配置信息出错，请检查网络和中台服务是否开启.中台服务代码:' + serviceCenterCode,
                type: 'warning'
            });
            return serviceCenters;
        }
        if ( serviceCenters.length === undefined ) return serviceCenters;
        for ( let index = 0; index < serviceCenters.length; index++) {
            let serviceCenter = serviceCenters[index];
            ServiceCenter[serviceCenter.code] = serviceCenter.value;
        }
        return serviceCenters;
    },
    axiosGet(url, where, serviceCenterCode, options) {
        //console.info("begin axiosGet ======" + url + JSON.stringify(where));
        let config = {};        //还可以设置其它配置，这里先空着。
        if ( options ) {
            config = {...config, ...options};   //如果有传入配置，则合并.
            console.log('axiosGet=======merge=options==', config);
        }
        // 这里的params是axios定义的,不是HTTP协议头定义的。axios会将其转为?a=xx&b=yy形式然后放入URL后面。
        //serviceCenterCode中的各服务中心的主机地址，由VUE应用从权限中心的DB中获取。
        config.baseURL = ServiceCenter[serviceCenterCode];
        console.info('config.baseURL=beforeGet==' + config.baseURL + url);
        if ( config.baseURL === undefined ) {
            config.baseURL = axiosOptions.baseURL;
        }
        console.info('config.baseURL=afterGet==' + config.baseURL + url);

        config.params = where;            //axiosOptions中已经配置了paramsSerializer,所以这里直接赋值即可。
        //axiosService.get是异步方法.
        let that = this;
        return axiosService.get(url, config)
            .then(function (response) {     //这里的response是已经在respone拦截器中处理后的业务数据。
                    //这里可以再次处理业务数据，然后再返回。
                    console.log("========in axiosGet then ===========" + JSON.stringify(response));
                    if ( response.code === "0") {
                        if ( options ) {
                            if ( options.showMessage === true ) {
                                that.message({duration: 2000, showClose: true, message: response.message, type: 'success'});
                            }
                        }else if ( that.showMessage === true ) {
                            that.message({showClose: true, message: response.message, type: 'success'});
                        }
                        if ( response.data !== undefined ) {
                            console.log("========in axiosGet where ===========" + JSON.stringify(where));
                            if (where && where.pageRange) {
                                where.pageRange.total = response.count;
                                console.log("========in axiosGet where ===========1" + JSON.stringify(where));

                            }else {
                                let where = { pageRange: {total: 0} };
                                where.pageRange.total = response.count;
                            }
                            return response.data;
                        }      //表示列表数据
                        if ( response.datum !== undefined ) return response.datum;    //表示单个数据
                    }else if ( response.code === "-1") {         // code !== "0",已经在axiosService.interceptors.response.use中抛出异常.
                        console.info("axiosGet error ==== " + 11);
                        that.warning({
                            title: '失败',
                            message: response.message,
                            position: 'bottom-right',
                            type: 'warning'
                        });
                    }else {
                        console.info("axiosGet error");
                    }
                    return response;
                })
            .catch(function (error) {                       //如果respone拦截器没有返回response,则认为是错误。
                that.error({
                    title: '错误',
                    position: 'bottom-right',
                    message: error.message,
                    type: 'error'
                });
                console.log("========in axiosGet catch ===========" + JSON.stringify(error));
                });
    },
    //使用POST进行查询
    axiosPost(url, where, serviceCenterCode, options) {
        //        let params = qs.stringify(data);
        let config = {};        //还可以设置其它配置，这里先空着。
        if ( options ) {
            config = {...config, ...options};   //如果有传入配置，则合并.
            console.log('axiosPost=======merge=options==', config);
        }
        //serviceCenterCode中的各服务中心的主机地址，由VUE应用从权限中心的DB中获取。
        config.baseURL = ServiceCenter[serviceCenterCode];
        console.info('config.baseURL=beforePost==' + config.baseURL + url);
        if ( config.baseURL === undefined ) {
            config.baseURL = axiosOptions.baseURL;
        }
        console.info('config.baseURL=afterPost==' + config.baseURL + url);

        if ( config.headers === undefined ) config.headers = {};
        //putHeaders(config.headers, 'Content-Type', 'application/json;charset=utf-8');
        //config.params = where;            //axiosOptions中已经配置了paramsSerializer,所以这里直接赋值即可。
        let that = this;
        return axiosService.post(url, where, config)
            .then(function (response) {     //这里的response是已经在respone拦截器中处理后的业务数据。
                    //这里可以再次处理业务数据，然后再返回。
                    console.log("========in axiosGet then ===========" + JSON.stringify(response));
                    if ( response.code === "0") {
                        if ( options ) {
                            if ( options.showMessage === true ) {
                                that.message({duration: 2000, showClose: true, message: response.message, type: 'success'});
                            }
                        }else if ( that.showMessage === true ) {
                            that.message({showClose: true, message: response.message, type: 'success'});
                        }
                        if ( response.data !== undefined ) {
                            console.log("========in axiosGet where ===========" + JSON.stringify(where));
                            if (where && where.pageRange) {
                                where.pageRange.total = response.count;
                                console.log("========in axiosGet where ===========1" + JSON.stringify(where));

                            }else {
                                let where = { pageRange: {total: 0} };
                                where.pageRange.total = response.count;
                            }
                            return response.data;
                        }      //表示列表数据
                        if ( response.datum !== undefined ) return response.datum;    //表示单个数据
                    }else if ( response.code === "-1") {         // code !== "0",已经在axiosService.interceptors.response.use中抛出异常.
                        console.info("axiosGet error ==== " + 11);
                        that.warning({
                            title: '失败',
                            message: response.message,
                            position: 'bottom-right',
                            type: 'warning'
                        });
                    }else {
                        console.info("axiosGet error");
                    }
                    return response;
                })
            .catch(function (error) {                       //如果respone拦截器没有返回response,则认为是错误。
                that.error({
                    title: '错误',
                    position: 'bottom-right',
                    message: error.message,
                    type: 'error'
                });
                console.log("========in axiosGet catch ===========" + JSON.stringify(error));
                });
    },
    //使用POST进行增加，删除，修改
    axiosPostJSON(url, data, serviceCenterCode, options) {
//        let params = qs.stringify(data);
        let config = {};        //还可以设置其它配置，这里先空着。
        if ( options ) {
            config = {...config, ...options};   //如果有传入配置，则合并.
            console.log('axiosPost=======merge=options==', config);
        }
        //serviceCenterCode中的各服务中心的主机地址，由VUE应用从权限中心的DB中获取。
        config.baseURL = ServiceCenter[serviceCenterCode];
        console.info('config.baseURL=beforePost==' + config.baseURL + url);
        if ( config.baseURL === undefined ) {
            config.baseURL = axiosOptions.baseURL;
        }
        console.info('config.baseURL=afterPost==' + config.baseURL + url);

        if ( config.headers === undefined ) config.headers = {};
        //putHeaders(config.headers, 'Content-Type', 'application/json;charset=utf-8');
        let that = this;
        return axiosService.post(url, data, config)
            .then(function (response) {
                console.log("========in axiosPost then ===========" + JSON.stringify(response));
                if ( response.code === "0") {
                    if ( options ) {
                        if ( options.showMessage === true ) {
                            that.message({duration: 2000, showClose: true, message: response.message, type: 'success'});
                        }
                    }else if ( that.showMessage === true ) {
                        that.message({showClose: true, message: response.message, type: 'success'});
                    }
                    if ( response.data !== undefined ) {
                        console.log("========in axiosPost then response.data ===========" + JSON.stringify(response.data));
                        return response.data;
                    }      //表示列表数据
                    if ( response.datum !== undefined ) {
                        console.log("========in axiosPost then response.datum ===========" + JSON.stringify(response.datum));
                        return response.datum;
                    }    //表示单个数据
                }else {         // code !== "0",已经在axiosService.interceptors.response.use中抛出异常.
                    console.info("axiosGet error");
                }
                return response;
            })
            .catch(function (error) {
                that.error({
                    title: '错误',
                    position: 'bottom-right',
                    message: error.message,
                    type: 'error'
                });
                console.log("========in axiosPost catch ===========" + JSON.stringify(error));       //axiosService.post发出了请求，但是没有返回，为有错。
            });
    },
    //showMessage常用于主动操作后的反馈提示。与 Notification 的区别是, Notification更多用于系统级通知的被动提醒。
    //默认显示《用户主动操作后的反馈提示》，可以在main中修改为默认不显示。方法调用中options.showMessage优先级高于这里。
    showMessage: true,
    message: function(obj) {
        console.log('in message obj==', obj);
    },
    notify: function(result) {          //此方法用于：没有经过此包提交到服务时(没有经过axiosService.interceptors.response.use)，服务返回的各种信息。
        let webAddress = window.location.protocol + '//' + window.location.host;
        console.log('in notify result==', result);
        if ( result.code === "0") {     //业务处理结果成功.
            console.log("业务处理结果0:" + result.code + result.message);
            this.info({
                title: '通知',
                position: 'bottom-right',
                dangerouslyUseHTMLString: true,
                message: result.message,
                type: 'info'
            });
        }else if ( result.code === "-1") {    //未登录,
            console.info('result.code === 1未1登录');
            window.location.href = webAddress;
            console.info('result.code === 1未2登录');
            this.error({
                title: '错误',
                position: 'bottom-right',
                dangerouslyUseHTMLString: true,
                message: result.message,
                type: 'error'
            });
        }else if ( result.code ===  "-2") {   //登录过期了
            window.location.href = webAddress;
            this.error({
                title: '错误',
                position: 'bottom-right',
                dangerouslyUseHTMLString: true,
                message: result.message,
                type: 'error'
            });
        }else {
            this.error({
                title: '错误',
                position: 'bottom-right',
                dangerouslyUseHTMLString: true,
                message: result.message,
                type: 'error'
            });
        }
    },
    warning: function(obj) {
        console.log('in warning obj==', obj);
    },
    info: function(obj) {
        console.log('in info obj==', obj);
    },
    error: function(obj) {
        console.log('in error obj==', obj);
    },
    exportUrl(url, data, serviceCenterCode, options) {
        if ( (data === undefined) || (data === null) || (data === '') ) {
            data = {};
        }
        let token = getToken();
        if ( (token !== undefined) && (token !== null) && (token !== '') ) {
            data.token = token;
        }
        let re = qs.stringify(data, {encode: true, allowDots: true, allowSparse: true, indices: false, arrayLimit: 10000});
        return ServiceCenter[serviceCenterCode] + url + '?' + re;
    }
}
